<!--
=========================================================
* Argon Dashboard - v1.2.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard


* Copyright  Creative Tim (http://www.creative-tim.com)
* Coded by www.creative-tim.com



=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">

<head th:replace="fragments/common :: head_and_imports"></head>

<body>
<!-- Sidenav -->
<nav th:replace="fragments/common :: sidnav(2)"></nav>

<!-- Main content -->
<div class="main-content" id="panel">
	<!-- Topnav -->
	<nav class="navbar navbar-top navbar-expand navbar-dark bg-primary border-bottom d-md-none">
		<div class="container-fluid">
			<div class="collapse navbar-collapse row justify-content-between" id="navbarSupportedContent">
				<div class="row col-auto justify-content-end align-items-center m-0">
					<div class="col-auto">
						<ul class="navbar-nav align-items-center">
							<li class="nav-item d-xl-none">
								<!-- Sidenav toggler -->
								<div class="pr-2 sidenav-toggler sidenav-toggler-dark" data-action="sidenav-pin"
								     data-target="#sidenav-main">
									<div class="sidenav-toggler-inner">
										<i class="sidenav-toggler-line"></i>
										<i class="sidenav-toggler-line"></i>
										<i class="sidenav-toggler-line"></i>
									</div>
								</div>
							</li>
						</ul>
					</div>
				</div>
				<!-- Header -->
			
			</div>
		</div>
	</nav>
	
	<!-- Header -->
	<div class="header bg-primary">
		<div class="container-fluid">
			<!-- Header container -->
			<div class="container-fluid d-flex align-items-center">
				<div class="row">
					<div class="col-lg-10 col-md-10 mt-5 mb-8">
						<h1 class="display-2 text-white">Complexity Metrics</h1>
						<p class="text-white text-justify mb-3">
							This page is showing the metrics relevant to the complexity, including:
						</p>
						<p class="text-justify text-white mb-3 ml-4">
							<span class="text-bold">Number of Attributes</span>, which indicate the number of fields of a class.
						</p>
						<p class="text-justify text-white mb-3 ml-4">
							<span class="text-bold">Number of Local Methods</span><span>, </span>
							which count the methods that declared directly within the class.
						</p>
						<div class="collapse" id="collapse_description">
							<p class="text-justify text-white mb-1 ml-4">
								<span class="text-bold">Cyclomatic Complexity</span><span>, </span>
								which is derived from McCabe. T4M calculate this metric by enhancing
								McConnell's approach. We add 1 complexity if we meet the following syntax:
								<code>if</code>, <code>while</code>, <code>for</code>, <code>&&</code>, <code>||</code>
								<code>case or default of switch statement</code>, <code>catch of try statement</code>,
								and <code>ternary conditional expression ? :</code>.
							</p>
							<p class="text-white text-justify mb-3 ml-4">
								Detailed descriptions and influences:
								<a class="text-yellow text-link"
								   href="https://maisqual.squoring.com/wiki/index.php/Cyclomatic_Complexity">
									Maisqual - Cyclomatic Complexity</a>,
								<a class="text-yellow text-link" href="http://www.arisa.se/compendium/node96.html">
									ARiSA - McCabe Cyclomatic Complexity</a>.
							</p>
							<p class="text-justify text-white mb-1 ml-4">
								<span class="text-bold">Weighted Method Count</span><span>, </span>
								which is the sum of complexity of all local methods in a class.
							</p>
							<p class="text-white text-justify mb-3 ml-4">
								Detailed descriptions and influences:
								<a class="text-yellow text-link"
								   href="https://maisqual.squoring.com/wiki/index.php/Weighted_Methods_per_Class">
									Maisqual - Weighted Methods per Class</a>,
								<a class="text-yellow text-link" href="http://www.arisa.se/compendium/node97.html">
									ARiSA - Weighted Method Count</a>.
							</p>
							<p class="text-justify text-white mb-3 ml-4">
								<span class="text-bold">Max Complexity of Class</span><span>, </span>
								which is the maximum complexity of all local methods in a class.
							</p>
							<p class="text-justify text-white mb-3 ml-4">
								<span class="text-bold">Avg Complexity of Class</span><span>, </span>
								which is the average complexity of all local methods in a class.
							</p>
							<p class="text-justify text-white mb-1 ml-4">
								<span class="text-bold">Response For a Class</span><span>, </span>
								which is the number of methods which can respond to the message of a specific class.
								It is computed by counting a) the number of all methods including the inheritance methods but
								excluding the overwritten methods; b) the number of methods that are invoked by above methods.
							</p>
							<p class="text-white text-justify mb-3 ml-4">
								Detailed descriptions and influences:
								<a class="text-yellow text-link"
								   href="https://maisqual.squoring.com/wiki/index.php/Response_For_a_Class">
									Maisqual - Response For a class</a>,
								<a class="text-yellow text-link" href="http://www.arisa.se/compendium/node98.html">
									ARiSA - Response For a class</a>,
								<a class="text-yellow text-link"
								   href="https://www.oreilly.com/library/view/sonar-code-quality/9781849517867/ch09s04.html">
									Code Quality Testing Essentials - The Response for Class metric</a>.
							</p>
						</div>
						<a class="text-white text-link" data-toggle="collapse" href="#collapse_description"
						   role="button" aria-expanded="false" aria-controls="collapse_description">
							<i class="fas fa-sort"></i> Expand / Collapse
						</a>
					</div>
				</div>
			</div>
		</div>
	</div>
	
	<!-- Page content -->
	<div class="container-fluid mt--6" th:with="currentProjectInfo = ${projectList.get(projectList.size()-1)}">
		<!--图表-->
		<div class="row">
			<!-- chart -->
			<div class="col-xl-12">
				<div class="card">
					<div class="card-header bg-transparent">
						<div class="row align-items-center">
							<div class="col">
								<h6 class="text-muted text-uppercase ls-1 mb-1">Overview</h6>
								<h5 class="h3 mb-0" id="timeline_chart_title">
									{{ title }}
								</h5>
							</div>
							<div class="col">
								<ul class="nav nav-pills justify-content-end">
									<li class="nav-item mr-2 mr-md-0">
										<a href="javascript:void(0);" class="nav-link py-2 px-3 active"
										   data-toggle="tab"
										   onclick="showTimelineChartForClass()">
											<span class="d-none d-md-block">Class Level</span>
											<span class="d-md-none">C</span>
										</a>
									</li>
									<li class="nav-item">
										<a id='sloc_timeline_chart' href="javascript:void(0);" class="nav-link py-2 px-3"
										   data-toggle="tab" onclick="showTimelineChartForMethod()">
											<span class="d-none d-md-block">Method Level</span>
											<span class="d-md-none">F</span>
										</a>
									</li>
								</ul>
							</div>
						</div>
					</div>
					<div id="chart" class="card-body pb-4 px-4 pt-0 col-12" style="height:750px;"></div>
					<div class="modal fade" id="chart_data_model" tabindex="-1" role="dialog"
					     aria-labelledby="row_model_label" aria-hidden="true">
						<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable" role="document">
							<div class="modal-content">
								<div class="modal-header">
									<h5 class="modal-title">{{title}}</h5>
									<button type="button" class="close" data-dismiss="modal" aria-label="Close">
										<span aria-hidden="true">&times;</span>
									</button>
								</div>
								<div class="modal-body pt-0">
									<hr class="my-3">
									<div v-for="pointValue in pointValueList">
										<span>{{pointValue}}</span><br>
									</div>
									<hr class="my-3">
									<div v-for="pointDescription in pointDescriptionList">
										<div v-html="pointDescription"></div>
										<hr class="my-1">
									</div>
								</div>
								<div class="modal-footer">
									<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
								</div>
							</div>
						</div>
					</div>
					
					<script type="text/javascript" th:inline="javascript">
              let timeRecords = /*[[${timeRecords}]]*/;
              let weightedMethodsCountDataset = /*[[${weightedMethodsCountDataset}]]*/;
              let maxComplexityOfClassDataset = /*[[${maxComplexityOfClassDataset}]]*/;
              let avgComplexityOfClassDataset = /*[[${avgComplexityOfClassDataset}]]*/;
              let responseForClassDataset = /*[[${responseForClassDataset}]]*/;
              let methodComplexityDataset = /*[[${methodComplexityDataset}]]*/;
              let methodNumDataset = /*[[${methodNumDataset}]]*/;
              let currentChartLevel = 'class';
              let seriesName = ["Classes regarding the Average Complexity metric", "Classes regarding the Response For a Class metric",
                  "Classes regarding the Weighted Methods Count metric", "Classes regarding the Maximum Complexity metric"]

              let vm_for_timeline_chart_title = new Vue({
                  el: '#timeline_chart_title',
                  data: {
                      title: "The distribution of the classes on the number of its methods and four complexity metrics."
                  }
              })

              function showTimelineChartForClass() {
                  vm_for_timeline_chart_title.title = "The distribution of the classes on the number of its methods and four complexity metrics."
                  currentChartLevel = 'class';
                  let option = {
                      options: initOptions(),
                      baseOption: {
                          legend: {},
                          grid: [
                              {x: '7%', y: '5%', width: '40%', height: '35%', top: 50},
                              {x2: '5%', y: '5%', width: '40%', height: '35%', top: 50},
                              {x: '7%', y2: '11%', width: '40%', height: '35%', bottom: 100},
                              {x2: '5%', y2: '11%', width: '40%', height: '35%', bottom: 100}
                          ],
                          xAxis: [
                              {
                                  gridIndex: 0, name: 'Number of methods in a class',
                                  nameLocation: 'center', nameGap: 25
                              },
                              {
                                  gridIndex: 1, name: 'Number of methods in a class',
                                  nameLocation: 'center', nameGap: 25
                              },
                              {
                                  gridIndex: 2, name: 'Number of methods in a class',
                                  nameLocation: 'center', nameGap: 25
                              },
                              {
                                  gridIndex: 3, name: 'Number of methods in a class',
                                  nameLocation: 'center', nameGap: 25
                              },
                          ],
                          yAxis: [
                              {
                                  gridIndex: 0, name: 'Average Complexity of Class',
                                  nameLocation: 'center', nameRotate: 90, nameGap: 30
                              },
                              {
                                  gridIndex: 1, name: 'Response for a Class',
                                  nameLocation: 'center', nameRotate: 90, nameGap: 30
                              },
                              {
                                  gridIndex: 2, name: 'Weighted Methods Count',
                                  nameLocation: 'center', nameRotate: 90, nameGap: 30
                              },
                              {
                                  gridIndex: 3, name: 'Maximum Complexity of Class',
                                  nameLocation: 'center', nameRotate: 90, nameGap: 30
                              },
                          ],
                          dataZoom: [
                              {type: 'inside', xAxisIndex: 0, start: 0, end: 100},
                              {type: 'inside', yAxisIndex: 0, start: 0, end: 100},
                              {type: 'inside', xAxisIndex: 1, start: 0, end: 100},
                              {type: 'inside', yAxisIndex: 1, start: 0, end: 100},
                              {type: 'inside', xAxisIndex: 2, start: 0, end: 100},
                              {type: 'inside', yAxisIndex: 2, start: 0, end: 100},
                              {type: 'inside', xAxisIndex: 3, start: 0, end: 100},
                              {type: 'inside', yAxisIndex: 3, start: 0, end: 100},
                          ],
                          timeline: {
                              axisType: 'category', loop: true, autoPlay: false, currentIndex: timeRecords.length - 1,
                              playInterval: 1000, symbol: 'circle', data: timeRecords, animation: false,
                              controlStyle: {showNextBtn: true, showPrevBtn: true, showPlayBtn: true},
                              checkpointStyle: {animation: false},
                              label: {
                                  formatter: function (value, index) {
                                      return value.split(" ")[0];
                                  }
                              }
                          },
                          tooltip: {
                              padding: 10, borderWidth: 1,
                              show: true, enterable: true, trigger: 'item', confine: true,
                              formatter: function (params) {
                                  if (params.componentType === "timeline") {
                                      return params.name;
                                  } else if (params.componentType === "series") {
                                      let value = params.data
                                      let yLabelName = params.seriesName;
                                      return '<div style="border-bottom: 1px solid rgba(255,255,255,.3) ;padding-bottom: 7px;margin-bottom: 7px">'
                                          + 'Class: ' + value[2] + '<br>'
                                          + '<span style="font: 12px">'
                                          + 'Of module: ' + value[3] + '</span>' + '<br>'
                                          + '</div>'
                                          + '<div style="border-bottom: 1px solid rgba(255,255,255,.3) ;padding-bottom: 7px;margin-bottom: 7px">'
                                          + 'Number of Methods : ' + value[0] + '<br>'
                                          + yLabelName + ': ' + value[1] + '<br>'
                                          + '</div>'
                                          + 'Click the point to see all overlapped data.';
                                  }
                              }
                          },
                      },
                  };
                  document.getElementById("chart").style.height = "680px";
                  timelineChart.clear();
                  timelineChart.resize();
                  timelineChart.setOption(option);
              }

              function initOptions() {
                  let options = [];
                  for (let i = 0; i < timeRecords.length; i++) {
                      options[i] = {
                          series: [
                              {
                                  name: seriesName[0], animation: false,
                                  type: 'scatter', xAxisIndex: 0, yAxisIndex: 0,
                                  data: avgComplexityOfClassDataset[timeRecords[i]],
                                  emphasis: {
                                      label: {
                                          show: true,
                                          formatter: function (params) {
                                              return params.data[2];
                                          },
                                          color: '#000000',
                                          position: 'top',
                                          fontWeight: 'normal',
                                      },
                                  },
                              },
                              {
                                  name: seriesName[1], animation: false,
                                  type: 'scatter', xAxisIndex: 1, yAxisIndex: 1,
                                  data: responseForClassDataset[timeRecords[i]],
                                  emphasis: {
                                      label: {
                                          show: true,
                                          formatter: function (params) {
                                              return params.data[2];
                                          },
                                          color: '#000000',
                                          position: 'top',
                                          fontWeight: 'normal',
                                      },
                                  },
                              },
                              {
                                  name: seriesName[2], animation: false,
                                  type: 'scatter', xAxisIndex: 2, yAxisIndex: 2,
                                  data: weightedMethodsCountDataset[timeRecords[i]],
                                  emphasis: {
                                      label: {
                                          show: true,
                                          formatter: function (params) {
                                              return params.data[2];
                                          },
                                          color: '#000000',
                                          position: 'top',
                                          fontWeight: 'normal',
                                      },
                                  },
                              },
                              {
                                  name: seriesName[3], animation: false,
                                  type: 'scatter', xAxisIndex: 3, yAxisIndex: 3,
                                  data: maxComplexityOfClassDataset[timeRecords[i]],
                                  emphasis: {
                                      label: {
                                          show: true,
                                          formatter: function (params) {
                                              return params.data[2];
                                          },
                                          color: '#000000',
                                          position: 'top',
                                          fontWeight: 'normal',
                                      },
                                  },
                              },
                          ]
                      }
                  }
                  return options;
              }

              function showTimelineChartForMethod() {
                  vm_for_timeline_chart_title.title =
                      "The trends of the total number of methods in your project, and the trends of Cyclomatic Complexity values for these methods.";
                  currentChartLevel = 'method'
                  let option = {
                      grid: {
                          bottom: '100'
                      },
                      legend: {selected: {'Number of all methods': false},},
                      xAxis: {
                          name: "The Date of Record", type: 'category', splitArea: {interval: 0},
                          splitLine: {show: true, lineStyle: {type: 'solid'}}, nameLocation: 'center', nameGap: 28,
                          axisLabel: {
                              formatter: function (value, index) {
                                  return value.split(" ")[0];
                              }
                          }
                      },
                      yAxis: [{
                          name: "The Cyclomatic Complexity of methods", type: 'value',
                          nameLocation: 'center', nameRotate: 90, nameGap: 30
                      }, {
                          name: "Number of all methods in the project", type: 'value',
                          nameLocation: 'center', nameRotate: 270, nameGap: 35
                      }],
                      series: [{
                          name: 'Methods regarding the Cyclomatic Complexity',
                          type: 'scatter', yAxisIndex: 0, data: methodComplexityDataset,
                          emphasis: {
                              label: {
                                  show: true, color: '#000000', position: 'top', fontWeight: 'normal',
                                  formatter: function (params) {
                                      return params.data[2];
                                  },
                              },
                          },
                      }, {
                          name: 'Number of all methods', type: 'bar', yAxisIndex: 1,
                          data: methodNumDataset,
                          itemStyle: {color: 'rgba(229,229,229,0.8)',},
                          label: {
                              show: true, position: 'top', distance: 20, formatter: '{@[1]}', color: '#000000',
                          },
                          emphasis: {
                              itemStyle: {color: 'rgba(201,201,201,0.8)'},
                          }
                      }],
                      dataZoom: [
                          {type: 'slider', xAxisIndex: 0, start: 0, end: 100},
                          {type: 'inside', xAxisIndex: 0, start: 0, end: 100},
                          {type: 'slider', yAxisIndex: 0, left: 20, start: 0, end: 100},
                          {type: 'slider', yAxisIndex: 1, right: 20, start: 0, end: 100}
                      ],
                      tooltip: {
                          show: true, enterable: true, trigger: 'item', confine: true, padding: 10, borderWidth: 1,
                          formatter: function (params) {
                              if (params.componentSubType === "scatter") {
                                  let value = params.data
                                  return '<div style="border-bottom: 1px solid rgba(255,255,255,.3) ;padding-bottom: 7px;margin-bottom: 7px">'
                                      + 'Method: ' + value[2] + '<br>' + 'Declaration: ' + value[3] + '<br>'
                                      + params.seriesName + ": " + value[1]
                                      + '</div>'
                                      + 'Click the point to see all overlapped data.';
                              }
                          },
                      },
                  };
                  document.getElementById("chart").style.height = "550px";
                  timelineChart.clear();
                  timelineChart.resize();
                  timelineChart.setOption(option);
              }

              // 基于准备好的dom，初始化echarts实例
              let timelineChart = echarts.init(document.getElementById('chart'));

              let pointedData = [];
              timelineChart.on('mouseover', function (params) {
                  pointedData = params.data;
              })
              timelineChart.on('mouseout', function () {
                  pointedData = [];
              })

              // 用于显示timeline chart的重叠数据
              let chart_data_vm = new Vue({
                  el: '#chart_data_model',
                  data: {
                      title: '',
                      pointValueList: [],
                      pointDescriptionList: [],
                  }
              })
              let currentTimelineIndex = timeRecords.length - 1;
              timelineChart.on('timelinechanged', function (params) {
                  currentTimelineIndex = params.currentIndex
              });
              timelineChart.on('click', 'series.scatter', function (param) {
                  chart_data_vm.title = timeRecords[currentTimelineIndex];

                  let targetDataset;
                  let x = param.value[0];
                  let y = param.value[1];
                  if (currentChartLevel === 'class') {
                      let pointValueList = [];
                      pointValueList.push("Number of methods: " + param.value[0]);
                      pointValueList.push(param.seriesName + ": " + param.value[1]);
                      chart_data_vm.pointValueList = pointValueList;

                      if (param.seriesName === seriesName[0]) {
                          targetDataset = avgComplexityOfClassDataset;
                      } else if (param.seriesName === seriesName[1]) {
                          targetDataset = responseForClassDataset;
                      } else if (param.seriesName === seriesName[2]) {
                          targetDataset = weightedMethodsCountDataset;
                      } else if (param.seriesName === seriesName[3]) {
                          targetDataset = maxComplexityOfClassDataset;
                      }
                      let pointDescriptionList = [];
                      for (let key in targetDataset) {
                          if (key === timeRecords[currentTimelineIndex]) {
                              for (let row of targetDataset[key]) {
                                  if (row[0] === x && row[1] === y) {
                                      let text = '<span style="font: 12px">'
                                          + 'Class: ' + row[2] + '</span>' + '<br>'
                                          + '<span style="font: 12px">'
                                          + 'of Module: ' + row[3] + '</span>' + '<br>';
                                      pointDescriptionList.push(text);
                                  }
                              }
                          }
                      }
                      chart_data_vm.pointDescriptionList = pointDescriptionList;
                  } else {
                      let pointValueList = [];
                      pointValueList.push(param.seriesName + ": " + param.value[1]);
                      chart_data_vm.pointValueList = pointValueList;

                      let pointDescriptionList = [];
                      methodComplexityDataset.forEach(row => {
                          if (row[0] === x && row[1] === y) {
                              let text = '<span style="font: 12px">'
                                  + 'Method: ' + row[2] + '</span>' + '<br>'
                                  + '<span style="font: 12px">'
                                  + 'Declaration: ' + row[3] + '</span>' + '<br>';
                              pointDescriptionList.push(text);
                          }
                      });
                      chart_data_vm.pointDescriptionList = pointDescriptionList;
                  }

                  $('#chart_data_model').modal('show');
              });
					
					
					</script>
				
				</div>
			</div>
		</div>
		<!--表格-->
		<div class="row">
			<!-- 选择记录时间 -->
			<div class="col-xl-12">
				<div class="card-header border-0">
					<div class="row align-items-center">
						<div class="col-auto">
							<h6 class="text-uppercase text-muted ls-1 mb0">Details</h6>
							
							<!-- dropdown -->
							<div class="nav-item dropdown">
								<a class="nav-link pr-0" href="#" role="button" data-toggle="dropdown" aria-haspopup="true"
								   aria-expanded="false">
											<span class="h3 mb-0 mr-2" id="current_record_time"
											      th:text="${#dates.format(currentProjectInfo.getCreateDate(), 'yyyy-MM-dd HH:mm:ss')}"></span>
									<i class="fas fa-caret-down"></i>
								</a>
								<div class="dropdown-menu">
									<a th:class="${timeRecordStat.index} eq ${timeRecords.size()-1} ? 'dropdown-item active' : 'dropdown-item'"
									   href="javascript:void(0);"
									   th:each="timeRecord,timeRecordStat : ${timeRecords}"
									   th:onclick="selectRecordTime(this,[[${timeRecordStat.index}]])">
										<span th:text="${timeRecord}"></span>
									</a>
								</div>
							</div>
						
						</div>
					
					</div>
				</div>
			</div>
			<!--表格-->
			<div class="col-xl-12">
				<div class="card table-outline">
					<div class="table-responsive">
						<div id="toolbar">
							<div class="form-inline" role="form">
								<a id="complexity-previous-btn" class="btn btn-outline-primary btn-sm invisible"
								   href="javascript:void(0);"
								   onclick="showClassComplexity()">
									< previous</a>
							</div>
						</div>
						<table id="table"></table>
					</div>
				</div>
			</div>
			<!-- Modal -->
			<div class="modal fade" id="complexity_row_model" tabindex="-1" role="dialog"
			     aria-labelledby="complexity_row_model_label" aria-hidden="true">
				<div class="modal-dialog modal-dialog-centered modal-xl" role="document">
					<div class="modal-content">
						<div class="modal-header">
							<h5 class="modal-title" id="complexity_row_model_label">
								<span class="h3 text-uppercase text-muted mr-2">{{ recordType }}</span>
								<span class="h3">{{ recordName }}</span>
							</h5>
							<button type="button" class="close" data-dismiss="modal" aria-label="Close">
								<span aria-hidden="true">&times;</span>
							</button>
						</div>
						<div class="modal-body">
							<div id="complexity_row_chart" class="card-body pb-4 pr-4 pl-0 pt-0 col-12" style="height:450px;"></div>
						</div>
						<div class="modal-footer">
							<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
						</div>
					</div>
				</div>
			
			</div>
		
		</div>
		<!--common modals-->
		<modal th:replace="fragments/common :: modals"></modal>
		<!-- Footer -->
		<footer th:replace="fragments/common :: footer"></footer>
	</div>
</div>
<script th:replace="fragments/common :: footer_imports"></script>
<script>


    $(function () {
        // 首次渲染图表
        showTimelineChartForClass();
        // 首次渲染表格
        showClassComplexity();
    })

    let $table = $('#table')
    let projectRecordIndex = -1;
    let currentClassQualifiedName = "";
    let isCurrentLevelMethod = false;


    // 选择记录
    function selectRecordTime(obj, index) {
        projectRecordIndex = index;
        let newTime = $(obj).text()
        $('#current_record_time').text(newTime)
        $(obj).siblings().removeClass("active")
        $(obj).addClass("active");
        if (isCurrentLevelMethod) {
            showMethodComplexity(currentClassQualifiedName);
        } else {
            showClassComplexity();
        }
    }

    // 表格：类级别的度量数据
    function showClassComplexity() {
        isCurrentLevelMethod = false;
        let columns = [{
            field: 'chart', title: ''
        }, {
            field: 'name', title: 'Class Name', sortable: true,
            formatter: function (value, row) {
                return '<a href="javascript:void(0);" ' +
                    'onclick="showMethodComplexity(\'' + row.qualifiedName + '\')">' +
                    value + '</a>';
            },
        }, {
            field: 'numOfFields', title: 'Number of Attributes', sortable: true
        }, {
            field: 'numOfMethod', title: 'Number of Methods', sortable: true
        }, {
            field: 'weightedMethodsCount', title: 'Weighted Method Count', sortable: true
        }, {
            field: 'maxComplexity', title: 'Max Complexity of Class', sortable: true
        }, {
            field: 'avgComplexity', title: 'Avg Complexity of Class', sortable: true
        }, {
            field: 'responseForClass', title: 'Response For a Class', sortable: true
        }, {
            field: 'type', title: 'Class Type', sortable: true
        }, {
            field: 'declaration', title: 'Class Location', sortable: true
        }, {
            field: 'package', title: 'of Which Package', sortable: true
        }, {
            field: 'module', title: 'of Which Module', sortable: true
        }];
        $.get("/dashboard/complexity/table/class?projectRecordIndex=" + projectRecordIndex).done(function (data) {
            let dataset = data;
            //给每行前面加上趋势图按钮（弹出模态框）
            for (i = 0; i < dataset.length; i++) {
                dataset[i].chart =
                    '<a class="table-chart-icon" href="javascript:void(0);" data-toggle="modal" '
                    + 'data-target="#complexity_row_model" onclick="showTableChartForClass(\'' +
                    dataset[i].qualifiedName + '\')">'
                    + '<i class="fas fa-chart-bar"></i></a>'
            }
            buildTable($table, dataset, columns, 2, 0)
            $("#complexity-previous-btn").addClass("invisible");
        });
    }

    //表格：方法级别的度量数据
    function showMethodComplexity(qualifiedName) {
        currentClassQualifiedName = qualifiedName;
        isCurrentLevelMethod = true;
        let columns = [{
            field: 'name', title: 'Method Name', sortable: true,
        }, {
            field: 'declaration', title: 'Method Declaration', sortable: true
        }, {
            field: 'class', title: 'of Which Class', sortable: true
        }, {
            field: 'module', title: 'of Which Module', sortable: true
        }, {
            field: 'cyclomaticComplexity', title: 'Cyclomatic Complexity', sortable: true
        }];
        $.get("/dashboard/complexity/table/method?classQualifiedName=" + qualifiedName +
            "&projectRecordIndex=" + projectRecordIndex).done(function (data) {
            buildTable($table, data, columns, 1, 1)
            $("#complexity-previous-btn").removeClass("invisible");
        });
    }

    // 重新渲染表格
    function buildTable($el, dataset, columns, fixedNumber, fixedRightNumber) {
        $el.bootstrapTable('destroy').bootstrapTable({
            height: 500,
            columns: columns,
            data: dataset,
            toolbar: '#toolbar',
            search: true,
            showColumns: true,
            fixedColumns: true,
            fixedNumber: fixedNumber,
            fixedRightNumber: fixedRightNumber,
            // buttons: "",
            // buttonsPrefix: "",
            // buttonsClass: "btn btn-sm btn-outline-primary",
            showColumnsToggleAll: true,
            detailViewByClick: true,
            iconSize: "sm",
            showFullscreen: true,
        })
    }

    // 用于修改模块框title
    let complexity_table_chart_title_vm = new Vue({
        el: '#complexity_row_model_label',
        data: {
            recordType: '',
            recordName: '',
        }
    })

    // 指定图表的配置项和数据
    let tableChartOptForClass = {
        grid: {
            bottom: '100'
        },
        // 声明一个 X 轴，类目轴（category）。默认情况下，类目轴对应到 dataset 第一列。
        xAxis: {
            type: 'category'
        },
        yAxis: {},
        tooltip: {
            trigger: 'axis',
            axisPointer: {
                snap: true,
                type: "line",
            }
        },
        dataZoom: [
            {
                type: 'slider',
                xAxisIndex: 0,
                start: 0,
                end: 100
            },
            {
                type: 'inside',
                xAxisIndex: 0,
                start: 0,
                end: 100
            },
            {
                type: 'slider',
                yAxisIndex: 0,
                start: 0,
                end: 100
            }
        ],
    };
    let complexityTableChart = echarts.init(document.getElementById('complexity_row_chart'));
    complexityTableChart.setOption(tableChartOptForClass);

    function showTableChartForClass(qualifiedName) {
        complexity_table_chart_title_vm.recordName = qualifiedName;
        complexity_table_chart_title_vm.recordType = "Class";
        // 异步加载数据
        $.get("/dashboard/complexity/table/chart/class?qualifiedName=" + qualifiedName).done(function (data) {
            // 填入数据
            complexityTableChart.setOption({
                legend: {
                    data: ["Number of Method", "Weighted Method Count", "Max Complexity of Class",
                        "Avg Complexity of Class", "Response for Class"]
                },
                dataset: {
                    // 提供一份数据。
                    source: data
                },
                series: [
                    {
                        type: 'line', name: 'Number of Method',
                        lineStyle: {width: 3}, emphasis: {label: {show: true}}
                    },
                    {
                        type: 'line', name: 'Weighted Method Count',
                        lineStyle: {width: 3}, emphasis: {label: {show: true}}
                    },
                    {
                        type: 'line', name: 'Max Complexity of Class',
                        lineStyle: {width: 3}, emphasis: {label: {show: true}}
                    },
                    {
                        type: 'line', name: 'Avg Complexity of Class',
                        lineStyle: {width: 3}, emphasis: {label: {show: true}}
                    },
                    {
                        type: 'line', name: 'Response for Class',
                        lineStyle: {width: 3}, emphasis: {label: {show: true}}
                    },
                ],
            });
        });
    }

    // 让echarts在模态框打开后重新渲染
    $('#complexity_row_model').on('shown.bs.modal', function () {
        complexityTableChart.resize()
    })


</script>

</body>

</html>
